#include <extend.h>

void VarCopy( PCLIPVAR, PCLIPVAR );
void VarFree( PCLIPVAR );
void MsgStop( LPSTR, LPSTR );

extern PCLIPVAR _eval;

//----------------------------------------------------------------------------//

void _Array( PCLIPVAR pDest, LONG lLen )
{
   pDest->wType  = VT_ARRAY;
   pDest->wClass = 0;

   pDest->pOVM = _vmAlloc( ( lLen + 1 ) * sizeof( CLIPVAR ) );
}

//----------------------------------------------------------------------------//

void _AAdd( PCLIPVAR pArray, PCLIPVAR pValue )
{
   LONG lSize;

   if( pArray->wType == VT_ARRAY )
   {
      lSize = _vmSize( pArray->pOVM ) + sizeof( CLIPVAR );
      _vmRealloc( pArray->pOVM, lSize );
      _ASet( pArray, ( lSize / sizeof( CLIPVAR ) ) - 1, pValue );
   }
}

//----------------------------------------------------------------------------//

void _AGet( PCLIPVAR array, LONG lIndex, WORD wMask, PCLIPVAR v )
{
   if( array->wType == VT_ARRAY )
   {
      if( lIndex <= _ALen( array ) )
      {
         VarCopy( v, ( ( PCLIPVAR ) _vmLock( array->pOVM ) ) + lIndex );
         _vmUnLock( array->pOVM );
      }
      else
         MsgStop( "Error: Array access out of bounds", "Error" );
   }
}

//----------------------------------------------------------------------------//

void _ASet( PCLIPVAR array, LONG lIndex, PCLIPVAR v )
{
   VarCopy( ( ( PCLIPVAR ) _vmLock( array->pOVM ) ) + lIndex, v );
   _vmUnLock( array->pOVM );
}

//----------------------------------------------------------------------------//

void ASetStr( PCLIPVAR array, LONG lIndex, LPSTR szText )
{
   CLIPVAR cText;

   cText.wType  = VT_CHARACTER;
   cText.wClass = 0;
   cText.lLen   = _strlen( szText );
   cText.pOVM   = _vmAlloc( cText.lLen + 1 );
   _strcpy( _vmLock( cText.pOVM ), szText );
   _vmUnLock( cText.pOVM );
   _ASet( array, lIndex, &cText );
}

//----------------------------------------------------------------------------//

void _ASize( PCLIPVAR array, LONG lSize )
{
   LONG l;
   CLIPVAR temp;

   if( array->wType == VT_ARRAY )
   {
      for( l = _ALen( array ); l > lSize; l-- )  // only when decreasing size
      {
         _AGet( array, l, 0xFFFF, &temp );
         VarFree( &temp );
      }

      _vmRealloc( array->pOVM, ( lSize + 1 ) * sizeof( CLIPVAR ) );
   }
}

//----------------------------------------------------------------------------//

LONG _ALen( PCLIPVAR pArray )
{
   if( pArray->wType & VT_ARRAY )
   {
      return ( _vmSize( pArray->pOVM ) / sizeof( CLIPVAR ) ) - 1;
   }
   return 0;
}

//----------------------------------------------------------------------------//

void _ATail( PCLIPVAR pArray, PCLIPVAR pDest )
{
   if( pArray->wType == VT_ARRAY )
      _AGet( pArray, _ALen( pArray ), 0xFFFF, pDest );
}

//----------------------------------------------------------------------------//

LONG _AScan( PCLIPVAR pArray, PCLIPVAR pValue )
{
   LONG lLen, lAt = 1;
   CLIPVAR Item;
   BOOL bExit = FALSE;

   if( pArray->wType == VT_ARRAY )
   {
      lLen = _ALen( pArray );

      while( ( lAt <= lLen ) && ( ! bExit ) )
      {
         _AGet( pArray, lAt, 0xFFFF, &Item );

         if( ( Item.wType == VT_CHARACTER ) && ( pValue->wType == VT_CHARACTER ) )
         {
            bExit = _strcmp( _vmLock( Item.pOVM ), _vmLock( pValue->pOVM ) );
            _vmUnLock( Item.pOVM );
            _vmUnLock( pValue->pOVM );
            if( ! bExit )
               lAt++;
         }
         else
            lAt++;
      }
      return lAt;
   }

   return 0;
}

//----------------------------------------------------------------------------//

CLIPPER ARRAY()
{
   _Array( _eval, _parnl( 1 ) );
}

//----------------------------------------------------------------------------//

CLIPPER AADD()
{
   if( _pcount() == 2 )
      _AAdd( _param( 1, 0xFFFF ), _param( 2, 0xFFFF ) );
}

//----------------------------------------------------------------------------//

CLIPPER ASIZE()
{
   if( _pcount() == 2 )
      _ASize( _param( 1, 0xFFFF ), _parnl( 2 ) );
}

//----------------------------------------------------------------------------//

CLIPPER ATAIL()
{
   if( _pcount() == 1 )
      _ATail( _param( 1, 0xFFFF ), _eval );
}

//----------------------------------------------------------------------------//

CLIPPER ASCAN()
{
   if( _pcount() == 2 )
      _retnl( _AScan( _param( 1, -1 ), _param( 2, -1 ) ) );
   else
      _retnl( 0 );
}

//----------------------------------------------------------------------------//
